
package org.finegold.core.netty.server.modules.login.handler;

import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.finegold.core.netty.core.model.ResultCode;
import org.finegold.core.netty.core.model.ServerResponse;
import org.finegold.core.netty.core.session.Session;
import org.finegold.core.netty.core.session.SessionManager;
import org.finegold.core.netty.server.modules.Common;
import org.finegold.core.netty.server.modules.login.cmd.LoginCmd;
import org.finegold.core.netty.server.modules.login.cmd.ModuleId;
import org.finegold.core.netty.server.modules.login.entity.Login;
import org.finegold.core.tool.utils.ProtostuffUtil;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.lang.reflect.ParameterizedType;

/**
 * Description: 登录模块
 *
 * @author QinYueFeng
 * @since: 1.0
 * Create Date Time: 2018/7/16 16:13
 * Update Date Time:
 */
@Slf4j
public abstract class LoginHandlerImpl<T extends Login> implements LoginHandler {


	public abstract Boolean login(byte[] data, Class<T> clazz);
	public abstract Boolean logout(byte[] data, Class<T> clazz);



    /**
     * 登录
     *
     * @param session session
     * @param data    data
     * @return
     */
    @Override
    public  void login(Session session, byte[] data, Channel channel) {
        try {
			Class<T> tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
			Boolean flag = login(data, tClass);
			if(flag){
				Login loginEntity = ProtostuffUtil.deserialize(data, Login.class);
				// 判断是否在其他地方登录过
				boolean isOnline = SessionManager.isOnline(loginEntity.getUserId());
				if (isOnline) {
					// 移除会话,关闭连接
					SessionManager.removeSessionCloseSocket(loginEntity.getUserId());
				}
				// 加入会话
				if (SessionManager.putSession(loginEntity.getUserId(), session)) {
					session.setAttachment(loginEntity);
					log.info(":{}的用户登录了",loginEntity.getUserId());
				} else {
					throw new RuntimeException("加入会话失败");
				}
				Common.LoginNotifyClient(session, LoginCmd.HEART_BEAT);
			}else {
				// 通知客户端
				byte[] bytes = ProtostuffUtil.serialize("账号密码错误");
				ServerResponse response = new ServerResponse(ModuleId.LOGIN, LoginCmd.LOGIN_FALL, ResultCode.FAIL,bytes);
				channel.writeAndFlush(response);
			}

        }  catch (Exception e) {
            log.error("登录异常:{}", e.toString(), e);
        }
    }

    @Override
    public void logout(Session session, byte[] data, Channel channel) {
        try {
			Class<T> tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
			Boolean flag = logout(data, tClass);
			if(flag){
				Login login = ProtostuffUtil.deserialize(data, Login.class);
				SessionManager.removeSessionCloseSocket(login.getUserId());
				ServerResponse response = new ServerResponse(ModuleId.LOGIN, LoginCmd.HEART_BEAT, ResultCode.SUCCESS);
				channel.writeAndFlush(response);
			}else {
				// 失败通知客户端
				Common.LoginNotifyClient(session, LoginCmd.LOGOUT_FALL);
			}
        } catch (Exception e) {
            log.error("登出异常:{}", e.toString(), e);
        }
    }

}
